#include <string.h>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::cin;
using std::vector;
//要求大家实现一个自己的string去使用
class String 
{
public:
	String()
    :_pstr(new char[1]())//初始化并指向1字节的空间，后续会非常省事
                         //不需要去考虑很多的边界条件
    {

    }
    //explicit
	String(const char * pstr)
    :_pstr(new char[strlen(pstr) + 1]())
    {
        cout << "String(const char *)" << endl;
        strcpy(_pstr, pstr);
    }

	String(const String & rhs)
    :_pstr(new char[strlen(rhs._pstr) + 1]())
    {
        strcpy(_pstr, rhs._pstr);
    }
    ~String(){
        if(_pstr){
            delete [] _pstr;
            _pstr = nullptr;
        }
    }

    //  s1 = s2;
    String &operator=(const String & rhs){
        if(this != &rhs){
            //回收左操作数申请的堆空间
            delete [] _pstr;
            _pstr = new char[strlen(rhs._pstr) + 1]();
            strcpy(_pstr, rhs._pstr);
        }
        return *this;
    }
    //s1 = "hello"; 赋值运算符
    //String s1 = "hello";构造函数 隐式操作(此处会涉及一个关键字explicit)
    String &operator=(const char * pstr){
        String temp = String(pstr);
        *this = temp;
        return *this;
    }
    
    //s1 += s2;yes s1 = s1 + s2;
    //String s1 += s2;error 
    String &operator+=(const String & rhs){
        //1.先开辟空间，进行字符串值的复制操作
        char * temp = new char[strlen(_pstr) + strlen(rhs._pstr) + 1]();
        strcpy(temp, _pstr);
        strcat(temp, rhs._pstr);
        //2.回收左操作数的空间
        delete [] _pstr;
        //3.将指针指向新申请的这块空间
        _pstr = temp;

        //4.最后返回
        return *this;
    }
    // s1 += "hello";
    String &operator+=(const char * pstr){
        if(pstr){
            String temp(pstr);
            *this += temp;
        }
        return *this;
    }
	
    // cout << s1[0] << endl;
    // s1[0] = 'H';
    char &operator[](std::size_t index){
        if(index >= size()){
            //越界了
            static char nullchar = '\0';
            return nullchar;
        }
        return _pstr[index];
    }

    //第二个const修饰，表示什么意思？？？？const成员函数
    //有什么特性，不可以在该函数中修改数据成员，对于指针来说，不可以变更指向
    //第一个const表示的是什么意思？const char &
    //表示的是返回的char是一个常量引用，不可以被修改
    const char &operator[](std::size_t index) const{
        if(index >= size()){
            //越界了
            static char nullchar = '\0';
            return nullchar;
        }
        return _pstr[index];
    }
	
    std::size_t size() const{
        return strlen(_pstr);
    }

    const char* c_str() const{
        return _pstr;
    }
	
	friend bool operator==(const String &, const String &);
	friend bool operator!=(const String &, const String &);
	
	friend bool operator<(const String &, const String &);
	friend bool operator>(const String &, const String &);
	friend bool operator<=(const String &, const String &);
	friend bool operator>=(const String &, const String &);
	
	friend std::ostream &operator<<(std::ostream &os, const String &s);
	friend std::istream &operator>>(std::istream &is, String &s);

private:
	char * _pstr;
};

//String s3 = s1 + s2;
String operator+(const String & lhs, const String & rhs){
    //不可以直接去使用前面实现的+=运算符
    //因为这里面的两个参数都是const修饰，不可以变更
    String temp(lhs);
    temp += rhs;
    return temp;
}

String operator+(const String & lhs, const char * pstr){
    String temp(lhs);
    temp += pstr;
    return temp;
}
String operator+(const char * pstr, const String & rhs){
    String temp(pstr);
    temp += rhs;
    return temp;
}

bool operator==(const String & lhs, const String & rhs){
    return strcmp(lhs._pstr,rhs._pstr) == 0;
}
bool operator!=(const String & lhs, const String & rhs){
    return strcmp(lhs._pstr, rhs._pstr) != 0;
}
	
bool operator<(const String & lhs, const String & rhs){
    return strcmp(lhs._pstr, rhs._pstr) < 0;
}
bool operator>(const String & lhs, const String & rhs){

    return strcmp(lhs._pstr, rhs._pstr) > 0;
}
bool operator<=(const String & lhs, const String & rhs){

    return strcmp(lhs._pstr, rhs._pstr) <= 0;
}
bool operator>=(const String & lhs, const String & rhs){

    return strcmp(lhs._pstr, rhs._pstr) >= 0;
}
	
std::istream &operator>>(std::istream &is, String &s){
    if(s._pstr){
        //如果不为空，那么需要先把原先的空间给回收
        delete [] s._pstr;
        //is >> s._pstr;
    }
    char c;
    vector<char> vec;
    while((c = is.get()) != '\n'){
        //如果不是换行符，那么就让用户一直去输入
        vec.push_back(c);
    }
    char * temp = new char[vec.size() + 1]();
    for(size_t i = 0;i < vec.size(); ++i){
        temp[i] = vec[i];
    }
    s._pstr = temp;
    return is;
}

std::ostream &operator<<(std::ostream &os, const String &s){
    if(s._pstr){
        os << s._pstr;
    }
    return os;
}

void test(){
    String s1;
    String s2("hello");
    String s3(s2);
    cout << s1 << s2 << s3 << endl;
}
void test2(){
    String s1 = "hello";
    String s2 = "world";
    s1 += s2;
    cout << s1 << "::::" <<  s2 << endl;


    s2 += "c++";
    cout << s2 << endl;
}

void test3(){
    String s1 = "hello";
    cout << s1[0] << endl;
    s1[0] = 'H';
    cout << s1[0] << endl;
}

void test4(){
    String s1 = "hello";
    String s2 = "world";
    String s3 = s1 + s2;
    cout << s3 << endl;
}

void test5(){
    String s1 = "hello";
    String s3 = s1 + "world";
    cout << s3 << endl;
}

void test6(){
    String s1 = "hello";
    String s2 = "world";
    String s3 = "hello";
    cout << (s1 == s2) << endl;
    cout << (s1 == s3) << endl;
    cout << (s1 >= s2) << endl;
}

void test7(){
    String s1;
    cin >> s1;
    cout << s1 << endl;
}

int main()
{
    test7();
    return 0;
}


